package com.paul.common.utils;

import com.paul.common.constant.SystemConst;
import org.apache.commons.lang3.StringUtils;

import java.text.ParseException;
import java.text.ParsePosition;
import java.text.SimpleDateFormat;
import java.util.*;

/**
 * Created by zmk523@163.com on 2019/11/6 15:27
 */
public class DateUtil {

    /**
     * 根据输入天数及日期推算向前向后日期
     *
     * @param date 输入日期
     * @param day  整数往后推,负数往前移动
     * @return https://blog.csdn.net/sky786905664/article/details/52472058/
     */
    public static Date dayAddOrsubtract(Date date, Integer day) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.DATE, day);
        return calendar.getTime();
    }

    /**
     * 根据输入小时及日期推算向前向后日期
     *
     * @param date 输入日期
     * @param hour 整数往后推,负数往前移动
     * @return https://blog.csdn.net/sky786905664/article/details/52472058/
     */
    public static Date hourAddOrsubtract(Date date, Integer hour) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.HOUR, hour);
        return calendar.getTime();
    }

    /**
     * 根据输入分钟及日期推算向前向后日期
     *
     * @param date   输入日期
     * @param minute 整数往后推,负数往前移动
     * @return https://blog.csdn.net/sky786905664/article/details/52472058/
     */
    public static Date minuteAddOrsubtract(Date date, Integer minute) {
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(date);
        calendar.add(Calendar.MINUTE, minute);
        return calendar.getTime();
    }

    /**
     * Date类型数据转成String
     *
     * @param date
     * @return
     */
    public static String getStringDate(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        return formatter.format(date);
    }

    /**
     * DateTime类型数据转成String
     *
     * @param date
     * @return
     */
    public static String getStringDateTime(Date date) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        return formatter.format(date);
    }

    /**
     * 将短时间格式字符串转换为时间 yyyy-MM-dd
     *
     * @param strDate
     * @return
     */
    public static Date strToDate(String strDate) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd");
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDate, pos);
    }

    /**
     * 将短时间格式字符串转换为时间 yyyy-MM-dd hh:mm:ss
     *
     * @param strDateTime
     * @return
     */
    public static Date strToDateTime(String strDateTime) {
        SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
        ParsePosition pos = new ParsePosition(0);
        return formatter.parse(strDateTime, pos);
    }

    /**
     * 日期追加天数
     *
     * @param date 目标日期
     * @param day  需追加的天数
     * @return
     */
    public static Date addDay(Date date, Integer day) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.DAY_OF_MONTH, day);// 当前日期+day天
        return c.getTime();
    }

    /**
     * 日期追加月数
     *
     * @param date  目标日期
     * @param month 需追加的月数
     * @return
     */
    public static Date addMonth(Date date, Integer month) {
        Calendar c = Calendar.getInstance();
        c.setTime(date);
        c.add(Calendar.MONTH, month);// 今天+1天
        return c.getTime();
    }

    /**
     * 时间段转化为分钟  480-503;
     *
     * @param timeRangeArr 格式：08:00-08:23;09:53-09:55;12:53-14:55;17:53-17:55
     * @return list
     */
    public static List<Map<String, Object>> timeSlotsToList(String timeRangeArr) {
        List<Map<String, Object>> list = new ArrayList<>();
        if (StringUtils.isBlank(timeRangeArr)) {
            return list;
        }

        for (String timeRange : timeRangeArr.split(";")) {
            Map<String, Object> map = new HashMap<>();
            String[] strTimeArr = timeRange.split("-");

            String[] strBTimeArr = strTimeArr[0].split(":");
            Integer bIntTime = Integer.parseInt(strBTimeArr[0]) * 60 + Integer.parseInt(strBTimeArr[1]);

            String[] strETimeArr = strTimeArr[1].split(":");
            Integer eIntTime = Integer.parseInt(strETimeArr[0]) * 60 + Integer.parseInt(strETimeArr[1]);

            map.put("start", bIntTime);
            map.put("end", eIntTime);
            list.add(map);
        }
        return list;
    }

    /**
     * 判断当前时间在时间区间内
     * @param nowTime   当前时间
     * @param beginTime 开始时间
     * @param endTime   结束时间
     * @return
     */
    public static boolean isEffectiveDate(Date nowTime, Date beginTime, Date endTime) {
        long nTime = nowTime.getTime();
        long bTime = beginTime.getTime();
        long eTime = endTime.getTime();
        return nTime >= bTime && nTime <= eTime;
    }

    /**
     * 判断结束时间是否有效
     * @param nowTime 当前时间
     * @return
     */
    public static boolean isEffectiveDate(Date nowTime, Date endTime) {
        long nTime = nowTime.getTime();
        long eTime = endTime.getTime();
        return nTime <= eTime;
    }

    /**
     * 根据给定的日期获取当前周的第一天日期
     *
     * @param date
     * @return 日期
     */
    public static String getWeekByDate(Date date) {
        SimpleDateFormat sdf = new SimpleDateFormat(SystemConst.DATEPATTERN); // 设置时间格式
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        // 判断要计算的日期是否是周日，如果是则减一天计算周六的，否则会出问题，计算到下一周去了
        int dayWeek = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        if (1 == dayWeek) {
            cal.add(Calendar.DAY_OF_MONTH, -1);
        }
        cal.setFirstDayOfWeek(Calendar.MONDAY);// 设置一个星期的第一天，按中国的习惯一个星期的第一天是星期一
        int day = cal.get(Calendar.DAY_OF_WEEK);// 获得当前日期是一个星期的第几天
        cal.add(Calendar.DATE, cal.getFirstDayOfWeek() - day);// 根据日历的规则，给当前日期减去星期几与一个星期第一天的差值
//        System.out.println("所在周星期一的日期：" + sdf.format(cal.getTime()));
        return sdf.format(cal.getTime());
    }

    /**
     * 日期时区转换
     *
     * @param date           日期
     * @param nowTimeZone    当前时区
     * @param targetTimeZone 转换的时区
     * @return 日期
     */
    public static String timeZoneTransferOfDate(String date, String nowTimeZone, String targetTimeZone) {
        if (StringUtils.isBlank(date)) {
            return "";
        }
        if (nowTimeZone.equals(targetTimeZone)) {
            return date;
        }
        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(SystemConst.DATEPATTERN);
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(nowTimeZone));
        Date date1;
        try {
            date1 = simpleDateFormat.parse(date);
        } catch (ParseException e) {
//            System.out.println("日期转换出错。");
            return "";
        }
        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(targetTimeZone));
        return simpleDateFormat.format(date1);
    }

    /**
     * 日期时间时区转换
     *
     * @param dateTime       日期时间
     * @param nowTimeZone    当前时区
     * @param targetTimeZone 转换的时区
     * @return 日期时间
     */
    public static String timeZoneTransferOfDateTime(String dateTime, String nowTimeZone, String targetTimeZone) {
        if (StringUtils.isBlank(dateTime)) {
            return "";
        }
        if (nowTimeZone.equals(targetTimeZone)) {
            return dateTime;
        }

        return dateTime;
//        SimpleDateFormat simpleDateFormat = new SimpleDateFormat(SystemConst.DATETIMEPATTERN);
//        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(nowTimeZone));
//        Date date1;
//        try {
//            date1 = simpleDateFormat.parse(dateTime);
//        } catch (ParseException e) {
////            System.out.println("时间转换出错。");
//            return "";
//        }
//        simpleDateFormat.setTimeZone(TimeZone.getTimeZone(targetTimeZone));
//        return simpleDateFormat.format(date1);
    }

    public static String timeZoneTransferOfDateTime(Date date, String timezone) {
        return timeZoneTransferOfDateTime(DateUtil.getStringDate(date) + " 00:00:00", SystemConst.TIMEZONE, timezone);
    }

    /**
     * TODO
     * 根据当前时区，计算时区差h1 默认时区差h (跨天)
     *
     * @param bDate
     * @param eDate
     * @param nowTimeZone
     * @return
     */
    public static Map<String, String> dateTimeZone(Date bDate, Date eDate, String nowTimeZone) {
//        String strBTime = timeZoneTransferOfDateTime(getStringDate(bDate) + " 00:00:00", SystemConst.TIMEZONE, nowTimeZone);
//        String strETime = timeZoneTransferOfDateTime(getStringDate(eDate) + " 00:00:00", SystemConst.TIMEZONE, nowTimeZone);
        String strBTime = getStringDate(bDate) + " 00:00:00";
        String strETime = getStringDate(eDate) + " 00:00:00";
        Map<String, String> map = new HashMap<>();
        map.put("bDate", strBTime);
        map.put("eDate", strETime);
        return map;
    }

    /**
     * 获取当前月份第一天的日期 *
     *
     * @return 格式化后的日期
     */
    public static String getFirstDayOfThisMonth() {
        SimpleDateFormat myFormatter = new SimpleDateFormat(SystemConst.DATEPATTERN);
        Calendar cal = Calendar.getInstance();
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return myFormatter.format(cal.getTime());
    }

    /**
     * 给定一个日期 获取所在月份第一天的日期 *
     *
     * @param date 给定的日期
     * @return 格式化后的日期
     */
    public static String getFirstDayOfThisMonth(Date date) {
        return getFirstDayOfThisMonth(date, 0);
    }

    /**
     * 给定一个日期 获取所在月份第一天的日期 *
     *
     * @param date  给定的日期
     * @param month -1 代表上月 0代表当月 1代表次月 以此类推
     * @return 格式化后的日期
     */
    public static String getFirstDayOfThisMonth(Date date, int month) {
        SimpleDateFormat myFormatter = new SimpleDateFormat(SystemConst.DATEPATTERN);
        Calendar cal = Calendar.getInstance();
        cal.setTime(date);
        cal.add(Calendar.MONTH, month);
        cal.set(Calendar.DAY_OF_MONTH, 1);
        return myFormatter.format(cal.getTime());
    }

    /**
     * 根据日期获取当月第一天
     *
     * @param date
     * @return
     */
    public static String getMonthFirstDayStr(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 0);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        return format.format(calendar.getTime());
    }

    /**
     * 根据日期获取当月最后一天
     *
     * @param date
     * @return
     */
    public static String getMonthLastDayStr(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar = Calendar.getInstance();
        calendar.add(Calendar.MONTH, 1);
        calendar.set(Calendar.DAY_OF_MONTH, 0);
        return format.format(calendar.getTime());
    }

    /**
     * 根据日期获取下月第一天
     *
     * @param date
     * @return
     */
    public static String getFirstDayOfNextMonth(Date date) {
        SimpleDateFormat format = new SimpleDateFormat("yyyy-MM-dd");
        Calendar calendar = Calendar.getInstance();
        calendar.setTime(date);
        calendar.set(Calendar.DAY_OF_MONTH, 1);
        calendar.add(Calendar.MONTH, 1);
        return format.format(calendar.getTime());
    }

    /**
     * 交集判断
     *
     * @param timeRange 格式：08:00-08:23
     * @return
     */
    public static boolean timeRangeIntersection(String timeRange) {
        if (StringUtils.isBlank(timeRange)) {
            return false;
        }
        if (!timeRange.contains("-")) {
            return false;
        }
        if (timeRange.split("-").length != 2) {
            return false;
        }
        String[] timeStr = timeRange.split("-");
        Integer bIntTime = timeToM(timeStr[0]);
        Integer eIntTime = timeToM(timeStr[1]);

        Calendar now = Calendar.getInstance();//24小时计时
        Integer nIntTime = timeToM(now.get(Calendar.HOUR_OF_DAY) + ":" + now.get(Calendar.MINUTE));
        if (nIntTime > bIntTime && nIntTime < eIntTime) {
            return true;
        }
        return false;
    }

    /**
     * 时分转化为分钟  480;
     *
     * @param timeRange 格式：08:00
     * @return int
     */
    public static Integer timeToM(String timeRange) {
        if (StringUtils.isBlank(timeRange)) {
            return 0;
        }
        if (!timeRange.contains(":")) {
            return 0;
        }
        if (timeRange.split(":").length != 2) {
            return 0;
        }
        String[] timeArr = timeRange.split(":");
        return Integer.parseInt(timeArr[0]) * 60 + Integer.parseInt(timeArr[1]);
    }


    /**
     * 获取两个时间相差分钟数
     *
     * @param oldDate
     * @param newDate
     * @return
     */
    public static long getTime(Date oldDate, Date newDate) {
        long NTime = newDate.getTime();
        //从对象中拿到时间
        long OTime = oldDate.getTime();
        return (NTime - OTime);
    }


    /**
     * 判断两个时间相差分钟数
     * @param oldDate
     * @param newDate
     * @param min
     * @return
     */
    public static boolean isMinutesDiff(Date oldDate, Date newDate, Integer min) {
        Integer diff = Math.toIntExact(getTime(oldDate, newDate) / 60000);
        return diff < min;
    }

}
